﻿Ext.lib.Component = Ext.extend(Ext.util.Observable, {
    isComponent: true,

    //渲染时模板
    renderTpl: null,

    //渲染方式，有覆盖和追加两种
    tplWriteMode: 'overwrite',

    //组件样式前缀，用于组合成样式类的名称
    baseCls: 'x-component',

    //组件禁用时的样式类名
    disabledCls: 'x-item-disabled',

    //是否隐藏
    hidden: false,

    //是否禁用
    disabled: false,

    //是否能拖拽
    draggable: false,

    //是否浮动
    floating: false,

    //读取html页面内容时是否连html中的样式也一起采用
    styleHtmlContent: false,

    //当styleHtmlContent为true时给组件添加的样式
    styleHtmlCls: 'x-html',

    //组件的DOM结点是否可移动，即是否可以改变它在DOM结点树的位置
    allowDomMove: true,

    //设置浮动或拖拽属性的时候是否自动显示
    autoShow: false,

    //自动绘制，在子类中用到
    autoRender: false,

    needsLayout: false,

    rendered: false,

    constructor: function (config) {
        config = config || {};
        this.initialConfig = config;
        Ext.apply(this, config);

        this.addEvents(

             'beforeactivate',

             'activate',

             'beforedeactivate',

             'deactivate',

             'added',

             'disable',

             'enable',

             'beforeshow',

             'show',

             'beforehide',

             'hide',

             'removed',

             'beforerender',

             'render',

             'afterrender',

             'beforedestroy',

             'destroy',

             'resize',

             'move',

             'beforestaterestore',
             'staterestore',
             'beforestatesave',
             'statesave'
        );

        //获取组件id，如果没有则自动生成，赋给this.id
        this.getId();

        this.mons = [];
        this.additionalCls = [];
        this.renderData = this.renderData || {};
        this.renderSelectors = this.renderSelectors || {};

        //调用私有初始化函数，未实现
        this.initComponent();

        //向组件管理类注册组件类
        Ext.ComponentMgr.register(this);

        //调用父类构造方法
        Ext.lib.Component.superclass.constructor.call(this);

        //如果有插件
        if (this.plugins) {
            this.plugins = [].concat(this.plugins);
            for (var i = 0, len = this.plugins.length; i < len; i++) {
                this.plugins[i] = this.initPlugin(this.plugins[i]);//启动每个插件
            }
        }

        //如果是以applyTo方式渲染
        if (this.applyTo) {
            this.applyToMarkup(this.applyTo);//未实现
            delete this.applyTo;
        }
        //如果是以renderTo方式渲染
        else if (this.renderTo) {
            this.render(this.renderTo);//在this.renderTo指定的文档节点上渲染
            delete this.renderTo;
        }

        if (Ext.isDefined(this.disabledClass)) {
            throw "Component: disabledClass has been deprecated. Please use disabledCls.";
        }
    },

    initComponent: Ext.emptyFn,
    applyToMarkup: Ext.emptyFn,

    show: Ext.emptyFn,

    //给组件布局，子类会用到
    onShow: function () {

        var needsLayout = this.needsLayout;
        if (Ext.isObject(needsLayout)) {
            this.doComponentLayout(needsLayout.width, needsLayout.height, needsLayout.isSetSize);
        }
    },

    //启动插件
    initPlugin: function (plugin) {
        if (plugin.ptype && typeof plugin.init != 'function') {
            plugin = Ext.PluginMgr.create(plugin);
        }
        else if (typeof plugin == 'string') {
            plugin = Ext.PluginMgr.create({
                ptype: plugin
            });
        }

        plugin.init(this);//运行插件的init方法

        return plugin;
    },

    //在container上渲染组件
    render: function (container, position) {
        if (!this.rendered && this.fireEvent('beforerender', this) !== false) {

            //如果组件的Ext.Element存在
            if (this.el) {
                this.el = Ext.get(this.el);
            }

            //初始化容器，把容器封装成DOM节点元素（Ext.Element）
            container = this.initContainer(container);

            //在container容器的position位置绘制组件
            this.onRender(container, position);
            this.fireEvent('render', this);

            //初始化组件内部，这里是对this.html、this.contentEl和this.tpl的使用
            this.initContent();

            //渲染后处理
            this.afterRender(container);
            this.fireEvent('afterrender', this);

            //初始化内部事件，即组件如果有一些子元素，之前给那些子元素注册侦听函数，
            //但是由于组件还没有渲染，那些子元素尚未创建，所以先把指向那些子元素的属性和对应的侦听函数先保存下来，
            //到了这一步再取出那些子元素和对应的侦听函数，给那些子元素注册侦听函数
            this.initEvents();

            //如果自动显示
            if (this.autoShow) {
                //调用show方法，该方法在子类Ext.Component中实现
                //show方法支持初始化后再渲染，是Ext.Component区别于Ext.lib.Component的重要特征
                this.show();
            }

            //如果隐藏
            if (this.hidden) {
                //隐藏组件，该方法在子类Ext.Component中实现
                //隐藏功能是Ext.Component区别于Ext.lib.Component的重要特征
                this.onHide(false);
            }

            //如果禁用
            if (this.disabled) {

                //禁用组件
                this.disable(true);
            }
        }

        return this;
    },

    //在container元素的position位置上绘制组件
    onRender: function (container, position) {
        var el = this.el,
            renderTpl,
            renderData;

        //获取指定位置的DOM结点
        position = this.getInsertPosition(position); // position为dom节点或id或容器节点子dom索引

        //如果组件还没有DOM节点元素
        if (!el) {

            if (position) {
                //创建新的DOM结点并插入到position之前，getElConfig方法获取描述组件DOM节点的对象
                el = Ext.DomHelper.insertBefore(position, this.getElConfig(), true);
            }
            else {
                //创建新的DOM结点并加入到container中，作为container的最后一个子结点 
                el = Ext.DomHelper.append(container, this.getElConfig(), true);
            }
        }
        //如果组件已经有了DOM结点元素，且DOM结点可以移动
        else if (this.allowDomMove !== false) {
            //将组件DOM结点插入到container中，作为containerDOM结点的第一个子结点
            container.dom.insertBefore(el.dom, position);
        }

        //initCls：初始化组件各样式类名，将各类名放入数组返回
        //将样式类的名称赋予组件DOM结点，使其能够应用这些样式
        el.addCls(this.initCls());

        //initStyles：整理组件的style、padding、margin、border等配置属性，返回一个封装了样式信息的对象
        //给组件DOM结点赋样式值
        el.setStyle(this.initStyles());

        //创建组件初始化模板
        renderTpl = this.initRenderTpl();

        if (renderTpl) {

            //构建组件初始化渲染的数据（this.baseCls和this.componentCls也包括其中）
            renderData = this.initRenderData();

            //以追加的方式渲染模板
            renderTpl.append(el, renderData);
        }

        this.el = el;

        //查询组件中符合this.renderSelectors对象中的各选择符的第一个DOM元素，
        //并把它们依次赋给组件同名属性
        this.applyRenderSelectors();

        //说明该组件已经渲染
        this.rendered = true;
    },

    //初始化组件各样式类名，将各类名放入数组返回
    initCls: function () {

        var cls = [this.baseCls]; //将this.baseCls收入cls数组

        if (this.componentCls) {
            cls.push(this.componentCls); //将this.componentCls收入cls数组
        }
        else {
            this.componentCls = this.baseCls;
        }
        if (this.cls) {
            cls.push(this.cls); //将this.cls收入cls数组
            delete this.cls;
        }
        if (this.ui) {
            cls.push(this.componentCls + '-' + this.ui); //将ui构造的类名收入cls数组
        }
        return cls.concat(this.additionalCls);//将this.additionalCls数组并入cls数组
    },

    //渲染后处理，主要实现布局定义，调整组件坐标位置、大小，设定读取的页面元素的样式
    afterRender: function () {

        //获取组件布局类，如果没有定义布局类，则创建默认布局类
        this.getComponentLayout();

        //如果指定了坐标
        if (this.x || this.y) {
            this.setPosition(this.x, this.y);//给组件定位
        }

        //如果使用读取的页面元素的样式
        if (this.styleHtmlContent) {
            this.getTargetEl().addCls(this.styleHtmlCls);
        }

        //如果组件没有外层容器（这里的容器指的是sencha-touch的容器组件），则设置其大小
        if (!this.ownerCt) {
            this.setSize(this.width, this.height);
        }
    },

    //获取描述组件DOM节点的对象
    getElConfig: function () {
        return { tag: 'div', id: this.id };
    },

    //获取指定位置的DOM结点
    getInsertPosition: function (position) {

        if (position !== undefined) {
            
            //如果position是数字
            if (Ext.isNumber(position)) {
                position = this.container.dom.childNodes[position];//获取容器在position位置的结点
            }
            //否则直接获取position的DOM
            else {
                position = Ext.getDom(position); // position为dom节点或id
            }
        }

        return position;
    },

    //初始化容器
    initContainer: function (container) {

        //如果没有指定容器，且组件已经创建了DOM结点元素，则把组件DOM结点的父结点作为容器
        if (!container && this.el) {
            container = this.el.dom.parentNode;
            this.allowDomMove = false;//规定组件的DOM结点不可移动
        }

        //获取容器DOM结点元素(Ext.Element)
        this.container = Ext.get(container);

        //如果指定了容器样式
        if (this.ctCls) {
            this.container.addCls(this.ctCls);//给容器添加样式
        }

        return this.container;
    },

    //构建组件初始化渲染的数据（this.baseCls和this.componentCls也包括其中）
    initRenderData: function () {
        return Ext.applyIf(this.renderData, {
            baseCls: this.baseCls,
            componentCls: this.componentCls
        });
    },

    //创建组件初始化模板
    initRenderTpl: function () {
        var renderTpl = this.renderTpl;
        if (renderTpl) {
            if (this.proto.renderTpl !== renderTpl) {
                if (Ext.isArray(renderTpl) || typeof renderTpl === "string") {
                    renderTpl = new Ext.XTemplate(renderTpl);
                }
            }
            else if (Ext.isArray(this.proto.renderTpl)) {
                renderTpl = this.proto.renderTpl = new Ext.XTemplate(renderTpl);
            }
        }
        return renderTpl;
    },

    //整理组件的style、padding、margin、border等配置属性，返回一个封装了样式信息的对象
    initStyles: function () {
        var style = {},
            Element = Ext.Element,
            i, ln, split, prop;

        //如果this.style是字符串，把它配置成对象
        if (Ext.isString(this.style)) {
            split = this.style.split(';');
            for (i = 0, ln = split.length; i < ln; i++) {
                if (!Ext.isEmpty(split[i])) {
                    prop = split[i].split(':');
                    style[Ext.util.Format.trim(prop[0])] = Ext.util.Format.trim(prop[1]);
                }
            }
        } else {
            style = Ext.apply({}, this.style);//如果是对象则直接复制
        }


        //将padding的值赋给对象
        if (this.padding != undefined) {
            style.padding = Element.unitizeBox((this.padding === true) ? 5 : this.padding);
        }

        //将margin的值赋给对象
        if (this.margin != undefined) {
            style.margin = Element.unitizeBox((this.margin === true) ? 5 : this.margin);
        }

        //将border的值赋给对象
        if (this.border != undefined) {
            style.borderWidth = Element.unitizeBox((this.border === true) ? 1 : this.border);
        }

        delete this.style;
        return style;
    },

    //初始化组件内部，这里是对this.html、this.contentEl和this.tpl的使用
    initContent: function () {

        //返回当前组件的DOM元素
        var target = this.getTargetEl();

        //如果定义了this.html
        if (this.html) {
            //将this.html加工成html格式的字符串后直接赋给组件DOM的innerHTML
            target.update(Ext.DomHelper.markup(this.html));
            delete this.html;
        }

        //如果定义了this.contentEl
        if (this.contentEl) {

            //获取页面中以this.contentEl为id的DOM元素
            var contentEl = Ext.get(this.contentEl);
            contentEl.show();

            //将contentEl插入到组件DOM中，作为他的最末尾的元素
            target.appendChild(contentEl.dom);
        }

        //如果定义了this.tpl
        if (this.tpl) {

            if (!this.tpl.isTemplate) {
                this.tpl = new Ext.XTemplate(this.tpl);//创建模板
            }

            //如果定义了this.data
            if (this.data) {

                //以指定模式渲染this.tpl模板，采用的数据是this.data
                this.tpl[this.tplWriteMode](target, this.data);
                delete this.data;
            }
        }
    },

    //初始化内部事件，即组件如果有一些子元素，之前给那些子元素注册侦听函数，
    //但是由于组件还没有渲染，那些子元素尚未创建，所以先把指向那些子元素的属性和对应的侦听函数先保存下来，
    //到了这一步在取出那些子元素和对应的侦听函数，给那些子元素注册侦听函数
    initEvents: function () {

        //定义渲染后再响应的事件，简单地说，如果想给组件的属性（指向一些类或子元素）添加侦听函数，
        //但是添加（调用addListener方法）侦听函数时该属性还没存在或为空，这时候就把属性和侦听函数
        //先加到this.afterRenderEvents中。
        //改方法正是渲染以后将侦听函数再次取出，给那些子元素组成侦听函数
        var afterRenderEvents = this.afterRenderEvents,
            property, listeners;

        //如果存在渲染后才能注册的侦听函数
        if (afterRenderEvents) {
            for (property in afterRenderEvents) {
                if (!afterRenderEvents.hasOwnProperty(property)) {
                    continue;
                }

                //取出侦听函数
                listeners = afterRenderEvents[property];

                //如果侦听函数对应的元素存在
                if (this[property] && this[property].on) {
                    this.mon(this[property], listeners);//给该元素注册侦听函数
                }
            }
        }
    },

    //查询组件中符合this.renderSelectors对象中的各选择符的第一个DOM元素，
    //并把它们依次赋给组件同名属性
    applyRenderSelectors: function () {
        var selectors = this.renderSelectors || {},
            el = this.el.dom,
            selector;

        //遍历渲染选择符对象的参数
        for (selector in selectors) {
            if (!selectors.hasOwnProperty(selector)) {
                continue;
            }

            //查询组件中符合选择符的第一个DOM元素，并把它赋给组件同名属性
            this[selector] = Ext.get(Ext.DomQuery.selectNode(selectors[selector], el));
        }
    },


    is: function (selector) {
        return Ext.ComponentQuery.is(this, selector);
    },


    up: function (selector) {
        var result = this.ownerCt;
        if (selector) {
            for (; result; result = result.ownerCt) {
                if (Ext.ComponentQuery.is(result, selector)) {
                    return result;
                }
            }
        }
        return result;
    },


    nextSibling: function (selector) {
        var o = this.ownerCt, it, last, idx, c;
        if (o) {
            it = o.items;
            idx = it.indexOf(this) + 1;
            if (idx) {
                if (selector) {
                    for (last = it.getCount(); idx < last; idx++) {
                        if ((c = it.getAt(idx)).is(selector)) {
                            return c;
                        }
                    }
                } else {
                    if (idx < it.getCount()) {
                        return it.getAt(idx);
                    }
                }
            }
        }
        return null;
    },


    previousSibling: function (selector) {
        var o = this.ownerCt, it, idx, c;
        if (o) {
            it = o.items;
            idx = it.indexOf(this);
            if (idx != -1) {
                if (selector) {
                    for (--idx; idx >= 0; idx--) {
                        if ((c = it.getAt(idx)).is(selector)) {
                            return c;
                        }
                    }
                } else {
                    if (idx) {
                        return it.getAt(--idx);
                    }
                }
            }
        }
        return null;
    },

    //获取组件id，如果没有则自动生成
    getId: function () {
        return this.id || (this.id = 'ext-comp-' + (++Ext.lib.Component.AUTO_ID));
    },

    getItemId: function () {
        return this.itemId || this.id;
    },

    //返回当前组件的DOM元素
    getEl: function () {
        return this.el;
    },

    //返回当前组件的DOM元素
    getTargetEl: function () {
        return this.el;
    },


    //测试组件是否是xtype指定的类的实例，如果shallow为true，则不算父类
    isXType: function (xtype, shallow) {

        if (Ext.isFunction(xtype)) {
            xtype = xtype.xtype;

        } else if (Ext.isObject(xtype)) {
            xtype = xtype.constructor.xtype;

        }

        return !shallow ? ('/' + this.getXTypes() + '/').indexOf('/' + xtype + '/') != -1 : this.constructor.xtype == xtype;
    },

    //获取组件类和上级类的xtype，放入列表返回
    getXTypes: function () {
        var constructor = this.constructor,
            xtypes = [],
            superclass = this,
            xtype;

        if (!constructor.xtypes) {
            while (superclass) {
                xtype = superclass.constructor.xtype;

                if (xtype != undefined) {
                    xtypes.unshift(xtype);
                }

                superclass = superclass.constructor.superclass;
            }

            constructor.xtypeChain = xtypes;
            constructor.xtypes = xtypes.join('/');
        }

        return constructor.xtypes;
    },

    //更新组件，用tpl模板渲染
    update: function (htmlOrData, loadScripts, cb) {

        //如果tpl模板已经定义，且htmlOrData不是字符串
        if (this.tpl && !Ext.isString(htmlOrData)) {
            this.data = htmlOrData;

            //如果组件已经渲染
            if (this.rendered) {
                //以指定模式渲染模板
                this.tpl[this.tplWriteMode](this.getTargetEl(), htmlOrData || {});
            }
        }
        //否则将htmlOrData加工成html标签形式的字符串
        else {
            this.html = Ext.isObject(htmlOrData) ? Ext.DomHelper.markup(htmlOrData) : htmlOrData;

            //如果组件已经渲染
            if (this.rendered) {
                //直接改变DOM结点的内容
                this.getTargetEl().update(this.html, loadScripts, cb);
            }
        }

        //如果组件已经渲染，则给组件布局
        if (this.rendered) {
            this.doComponentLayout();
        }
    },

    //设置组件的显示或隐藏
    setVisible: function (visible) {
        return this[visible ? 'show' : 'hide']();
    },

    //组件是否显示
    isVisible: function () {
        var visible = !this.hidden,
            cmp = this.ownerCt;


        this.hiddenOwnerCt = false;
        if (this.destroyed) {
            return false;
        };

        if (visible && this.rendered && cmp) {

            //向上遍历，只有当最顶层组件不是隐藏时，才返回true
            while (cmp) {
                if (cmp.hidden || cmp.collapsed) {

                    //当组件本身不是隐藏时，表示离组件最近的那个隐藏的上级容器，这时组件理论上也是隐藏的
                    this.hiddenOwnerCt = cmp;
                    visible = false;
                    break;
                }
                cmp = cmp.ownerCt;
            }
        }
        return visible;
    },

    //启用组件
    enable: function (silent) {

        //如果组件已经渲染
        if (this.rendered) {
            this.el.removeCls(this.disabledCls); //移除相应的样式
            this.el.dom.disabled = false;
            this.onEnable();
        }

        this.disabled = false;

        if (silent !== true) {
            this.fireEvent('enable', this);
        }

        return this;
    },

    //禁用组件
    disable: function (silent) {

        //如果组件已经渲染
        if (this.rendered) {
            this.el.addCls(this.disabledCls);//添加相应的样式
            this.el.dom.disabled = true;//将DOM结点的disabled属性设为true
            this.onDisable();
        }

        this.disabled = true;

        if (silent !== true) {
            this.fireEvent('disable', this);
        }

        return this;
    },

    //是否禁用
    isDisabled: function () {
        return this.disabled;
    },

    //设置组件的启用和禁用
    setDisabled: function (disabled) {
        return this[disabled ? 'disable' : 'enable']();
    },

    //组件是否隐藏
    isHidden: function () {
        return this.hidden;
    },

    //将参数传来的样式类的名称赋予组件DOM结点，使其能够应用这些样式
    addCls: function () {
        var me = this,
            args = Ext.toArray(arguments);
        if (me.rendered) {
            me.el.addCls(args);//将类名赋予DOM结点
        }
        else {
            me.additionalCls = me.additionalCls.concat(args);
        }
        return me;
    },

    addClass: function () {
        throw "Component: addClass has been deprecated. Please use addCls.";
    },

    //移除样式
    removeCls: function () {
        var me = this,
            args = Ext.toArray(arguments);
        if (me.rendered) {
            me.el.removeCls(args);
        }
        else if (me.additionalCls.length) {
            Ext.each(args, function (cls) {
                me.additionalCls.remove(cls);
            });
        }
        return me;
    },

    removeClass: function () {
        throw "Component: removeClass has been deprecated. Please use removeCls.";
    },

    //注册事件侦听函数
    addListener: function (element, listeners, scope, options) {
        if (Ext.isString(element) && (Ext.isObject(listeners) || options && options.element)) {
            if (options.element) {
                var fn = listeners,
                    option;

                listeners = {};
                listeners[element] = fn;
                element = options.element;
                if (scope) {
                    listeners.scope = scope;
                }

                for (option in options) {
                    if (!options.hasOwnProperty(option)) {
                        continue;
                    }
                    if (this.eventOptionsRe.test(option)) {
                        listeners[option] = options[option];
                    }
                }
            }


            //如果存在给定的子元素，且子元素有注册侦听函数的方法
            if (this[element] && this[element].on) {
                this.mon(this[element], listeners);//给子元素注册侦听函数
            }
            //否则先把事件名和侦听函数保存起来，等到渲染结束后再判断是否存在子元素以进而注册侦听函数
            else {
                this.afterRenderEvents = this.afterRenderEvents || {};
                this.afterRenderEvents[element] = listeners;
            }
        }

        //调用父类同名方法注册事件侦听函数
        return Ext.lib.Component.superclass.addListener.apply(this, arguments);
    },



    //获取上级组件
    getBubbleTarget: function () {
        return this.ownerCt;
    },

    //是否浮动
    isFloating: function () {
        return this.floating;
    },

    //是否可拖拽
    isDraggable: function () {
        return !!this.draggable;
    },

    //是否是可拖拽元素的对应组件
    isDroppable: function () {
        return !!this.droppable;
    },

    //关联上层容器
    onAdded: function (container, pos) {
        this.ownerCt = container;
        this.fireEvent('added', this, container, pos);
    },

    //将与上层容器的关联移除
    onRemoved: function () {
        this.fireEvent('removed', this, this.ownerCt);
        delete this.ownerCt;
    },


    onEnable: Ext.emptyFn,

    onDisable: Ext.emptyFn,

    beforeDestroy: Ext.emptyFn,


    onResize: Ext.emptyFn,

    //设置组件尺寸
    setSize: function (width, height) {

        if (Ext.isObject(width)) {
            height = width.height;
            width = width.width;
        }

        //当组件未渲染，或组件不是显示状态时
        if (!this.rendered || !this.isVisible()) {

            //当组件本身不是隐藏时，而上级容器隐藏时
            if (this.hiddenOwnerCt) {
                var layoutCollection = this.hiddenOwnerCt.layoutOnShow;
                layoutCollection.remove(this);
                layoutCollection.add(this);
            }
            this.needsLayout = {
                width: width,
                height: height,
                isSetSize: true
            };
            if (!this.rendered) {
                this.width = (width !== undefined) ? width : this.width;
                this.height = (height !== undefined) ? height : this.height;
            }
            return this;
        }

        //刷新布局
        this.doComponentLayout(width, height, true);

        return this;
    },

    //设置组件DOM尺寸，组件的宽高属性不变
    setCalculatedSize: function (width, height) {

        if (Ext.isObject(width)) {
            height = width.height;
            width = width.width;
        }
        if (!this.rendered || !this.isVisible()) {

            if (this.hiddenOwnerCt) {
                var layoutCollection = this.hiddenOwnerCt.layoutOnShow;
                layoutCollection.remove(this);
                layoutCollection.add(this);
            }
            this.needsLayout = {
                width: width,
                height: height,
                isSetSize: false
            };
            return this;
        }

        //刷新布局
        this.doComponentLayout(width, height);

        return this;
    },

    //给组件布局
    doComponentLayout: function (width, height, isSetSize) {

        //获取布局类，如果没有定义布局类，则创建默认布局类
        var componentLayout = this.getComponentLayout();

        if (this.rendered && componentLayout) {
            width = (width !== undefined || this.collapsed === true) ? width : this.width;
            height = (height !== undefined || this.collapsed === true) ? height : this.height;

            //如果连组件的宽和高的属性也重新设置
            if (isSetSize) {
                this.width = width;
                this.height = height;
            }

            //开始布局
            componentLayout.layout(width, height);
        }
        return this;
    },

    //给组件设置组件布局对象
    setComponentLayout: function (layout) {

        var currentLayout = this.componentLayout;

        //如果layout是新的布局对象
        if (currentLayout && currentLayout.isLayout && currentLayout != layout) {
            currentLayout.setOwner(null);//切断旧的布局对象与该组件的联系
        }
        this.componentLayout = layout; //设置组件新的布局对象

        layout.setOwner(this);//创建新布局对象与该组件的联系
    },

    //获取布局类，如果没有定义布局类，则创建默认布局类
    getComponentLayout: function () {

        //如果没有定义this.componentLayout，或则this.componentLayout不是一个布局对象
        if (!this.componentLayout || !this.componentLayout.isLayout) {

            //创建一个布局对象，默认为'autocomponent'类型
            //并为组件设置布局对象
            this.setComponentLayout(Ext.layout.LayoutManager.create(this.componentLayout, 'autocomponent'));
        }
        return this.componentLayout;
    },

    afterComponentLayout: Ext.emptyFn,

    //给组件定位（设了定位的组件才生效）
    setPosition: function (x, y) {
        if (Ext.isObject(x)) {
            y = x.y;
            x = x.x;
        }

        if (!this.rendered) {

            return this;
        }

        if (x !== undefined || y !== undefined) {
            this.el.setBox(x, y);//给组件DOM定位
            this.onPosition(x, y);
            this.fireEvent('move', this, x, y);
        }
        return this;
    },


    onPosition: Ext.emptyFn,

    //设置组件宽
    setWidth: function (width) {
        return this.setSize(width);
    },

    //设置组件高
    setHeight: function (height) {
        return this.setSize(undefined, height);
    },

    //设置组件尺寸
    getSize: function () {
        return this.el.getSize();
    },

    //获取组件宽
    getWidth: function () {
        return this.el.getWidth();
    },

    //获取组件高
    getHeight: function () {
        return this.el.getHeight();
    },

    //This method allows you to show or hide a LoadMask on top of this component.
    //此方法允许您显示或隐藏此组件上的LoadMask。
    //load : 为true时显示LoadMask，为false时隐藏LoadMask
    setLoading: function (load, targetEl) {

        //如果组件已经渲染
        if (this.rendered) {
            if (load) {
                //创建掩码控件
                this.loadMask = this.loadMask || new Ext.LoadMask(targetEl ? this.getTargetEl() : this.el, Ext.applyIf(Ext.isObject(load) ? load : {}));
                //显示掩码控件
                this.loadMask.show();
            } else {
                Ext.destroy(this.loadMask);
                this.loadMask = null;
            }
        }

        return this.loadMask;
    },

    //设置组件在父容器中的停靠位置
    setDocked: function (dock, layoutParent) {
        this.dock = dock;//停靠位置
        if (layoutParent && this.ownerCt && this.rendered) {
            this.ownerCt.doComponentLayout();
        }
        return this;
    },


    onDestroy: function () {
        if (this.monitorResize && Ext.EventManager.resizeEvent) {
            Ext.EventManager.resizeEvent.removeListener(this.setSize, this);
        }
        Ext.destroy(this.componentLayout, this.loadMask);
    },

    //销毁组件
    destroy: function () {

        //如果组件未销毁
        if (!this.isDestroyed) {
            if (this.fireEvent('beforedestroy', this) !== false) {
                this.destroying = true;//表示组件正在销毁
                this.beforeDestroy();

                //如果组件有上级容器，且上级容器有remove方法
                if (this.ownerCt && this.ownerCt.remove) {
                    this.ownerCt.remove(this, false);//从上级容器中移除
                }

                //如果已经渲染
                if (this.rendered) {
                    this.el.remove();//销毁DOM
                }

                this.onDestroy();

                Ext.ComponentMgr.unregister(this);//从组件管理类中注销
                this.fireEvent('destroy', this);

                this.clearListeners();//注销侦听函数
                this.destroying = false;//销毁结束
                this.isDestroyed = true;//状态为已经销毁
            }
        }
    }
});

Ext.lib.Component.prototype.on = Ext.lib.Component.prototype.addListener;
Ext.lib.Component.prototype.prev = Ext.lib.Component.prototype.previousSibling;
Ext.lib.Component.prototype.next = Ext.lib.Component.prototype.nextSibling;


Ext.lib.Component.AUTO_ID = 1000;